type t 'a = ref (option (Dllist.node_t 'a));

exception Empty;

value create () = ref None;

value is_empty t = !t = None;
value clear t = t.val := None;

value push_front t e =
  match !t with
  [ None -> t.val := Some (Dllist.create e)
  | Some q -> t.val := Some (Dllist.prepend q e)
  ];

value get_front t = 
  match !t with
  [ None -> raise Empty
  | Some q -> Dllist.get q
  ];

value drop_front t =
  match !t with
  [ None -> raise Empty
  | Some q -> 
      let nq = Dllist.drop q in
      (
        if nq == q 
        then t.val := None
        else t.val := Some nq
      )
  ];

value take_front t =
  match !t with
  [ None -> raise Empty
  | Some q -> 
    (
      let nq = Dllist.drop q in
        if nq == q
        then t.val := None
        else t.val := Some nq;
      Dllist.get q
    )
  ];

value push_back t e =
  match !t with
  [ None -> t.val := Some (Dllist.create e)
  | Some q -> Dllist.add (Dllist.prev q) e
  ];

value get_back t =
  match !t with
  [ None -> raise Empty
  | Some q -> Dllist.get (Dllist.prev q)
  ];

value drop_back t = 
  match !t with
  [ None -> raise Empty
  | Some q -> 
      let ln = Dllist.prev q in
      if ln == q 
      then t.val := None
      else Dllist.remove ln
  ];

value update_back t e =
  match !t with
  [ None -> raise Empty
  | Some q -> Dllist.set (Dllist.prev q) e
  ];


value iter ~f t =
  match !t with
  [ None -> ()
  | Some q -> Dllist.iter f q
  ];

value fold_left ~f r t = 
  match !t with
  [ None -> r
  | Some q -> Dllist.fold_left f r q
  ];

value fold_right ~f t r = 
  match !t with
  [ None -> r
  | Some q -> Dllist.fold_right f q r
  ];


value to_list t = 
  match !t with
  [ None -> []
  | Some q -> Dllist.to_list q
  ];
